package cn.xshi.gateway.route.timer;

import cn.hutool.core.collection.CollectionUtil;
import cn.xshi.gateway.route.client.GatewayNettyClient;
import cn.xshi.gateway.route.client.vo.ChannelEntity;
import cn.xshi.gateway.util.RouteInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * @Desc 定时器，监听路由节点变化
 * @Author 邓纯杰
 * @CreateTime 2022-10-15 05:32:17
 */
@Component
@Slf4j
public class RouteTimer implements CommandLineRunner{

    private static final String JEHC_CLOUD_OMP = "jehc-cloud-omp";//网关动态路由服务Server

    @Resource
    RouteInfo routeInfo;

    @Resource
    private GatewayNettyClient gatewayNettyClient;

    public boolean complete = true;//线程处理是否完成 false未完成 ture完成

    @Resource
    DiscoveryClient discoveryClient;

    @Override
    public void run(String... args) throws Exception {
        new Thread(new RouteTimerWorker()).start();
    }

    /**
     *
     */
    class RouteTimerWorker implements Runnable{
        public void run(){
            try {
                while (true){
                    try {
                        execute();
                    }catch (Exception e){
                        log.error("内部执行监听失败，信息：{}",e);
                    }finally {
                        Thread.sleep(1000);//1秒一次心跳连接
                    }
                }
            }catch (Exception e){
                log.error("外部执行监听失败，信息：{}",e);
            }
        }
    }

    /**
     * 执行监听
     */
    public void execute() {
        if(complete){
            try {
                complete = false;
                setGateWayAddressList();//定时更改
            }catch (Exception e){
                log.error("定时器监听路由节点变化异常，异常信息：",e);
            }finally {
                complete = true;
            }
        }
    }

    /**
     * 查询所有网关动态路由OMP模块中心服务所在物理机ip
     * @return
     */
    private void setGateWayAddressList(){
        try {
            List<ServiceInstance> serverAddressList = discoveryClient.getInstances(JEHC_CLOUD_OMP);
            if(CollectionUtil.isNotEmpty(serverAddressList)){//查询所有的客户端服务注册到nacos中心的时候 WEB服务自身所在的客户端IP
                List<String> list = new ArrayList<>();
                for(ServiceInstance serviceInstance : serverAddressList){
                    list.add(serviceInstance.getHost());
                }
                String result = list.stream().distinct().collect( Collectors.joining( "," ) );
                routeInfo.setHost(result);
                doChannel(list);
            }
        }catch (Exception e){
            log.info("查询动态路由OMP服务所在ip异常：{}",e);
        }
    }

    /**
     * 处理新增节点 重新加载到监听器中
     * @param list
     */
    private void doChannel(List<String> list){
        Map<String, ChannelEntity> channelEntityMap = gatewayNettyClient.getChannelEntityList();
        List<String> newList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(channelEntityMap)){
            Iterator<Map.Entry<String, ChannelEntity>> it = channelEntityMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, ChannelEntity> entry = it.next();
                ChannelEntity channelEntity = gatewayNettyClient.getChannelEntity(entry.getKey());
                if(null != channelEntity){
                    newList.add(channelEntity.getIp());
                }
            }
        }
        //判断集合一不在集合二中的数据
        List<String> ls = list.stream().filter(item->newList.stream().allMatch(each->!item.equals(each))).collect(Collectors.toList());
        String result = ls.stream().distinct().collect( Collectors.joining( "," ) );
        if(!StringUtils.isEmpty(result)){
            gatewayNettyClient.dynamicsLoad(result);
        }
    }
}
